package com.ibm.mq.point;


import com.ibm.mq.jms.MQQueue;
import com.ibm.mq.jms.MQQueueConnectionFactory;
import com.ibm.mq.jms.MQTopic;
import com.ibm.mq.point.config.ActiveMessageProducerMapper;
import com.ibm.mq.point.properties.ActiveBinderConfigurationProperties;
import com.ibm.mq.point.properties.ActiveConsumerProperties;
import com.ibm.mq.point.properties.ActiveExtendedBindingProperties;
import com.ibm.mq.point.properties.ActiveProducerProperties;
import com.ibm.mq.point.provisioning.ActiveProvisioner;
import com.ibm.msg.client.jms.internal.JmsTemporaryTopicImpl;
import com.ibm.msg.client.wmq.WMQConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cloud.stream.binder.*;
import org.springframework.cloud.stream.provisioning.ConsumerDestination;
import org.springframework.cloud.stream.provisioning.ProducerDestination;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.jms.DefaultJmsHeaderMapper;
import org.springframework.integration.jms.JmsHeaderMapper;
import org.springframework.integration.jms.JmsSendingMessageHandler;
import org.springframework.jms.connection.CachingConnectionFactory;
import org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;

import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.Message;
import java.util.Map;

@Slf4j
public class ActiveMessageChannelBinder extends AbstractMessageChannelBinder<ExtendedConsumerProperties<ActiveConsumerProperties>,
        ExtendedProducerProperties<ActiveProducerProperties>, ActiveProvisioner>
        implements ExtendedPropertiesBinder<MessageChannel, ActiveConsumerProperties, ActiveProducerProperties> {

    private static final String TYPE_TOPIC = "topic";

    private ActiveExtendedBindingProperties extendedProperties;

    private ActiveBinderConfigurationProperties activeBinderConfigurationProperties;

    @Override
    public Map<String, ?> getBindings() {
        return null;
    }

    @Override
    public String getDefaultsPrefix() {
        return "";
    }

    @Override
    public Class<? extends BinderSpecificPropertiesProvider> getExtendedPropertiesEntryClass() {
        return null;
    }


    public ActiveMessageChannelBinder(ActiveProvisioner provisioningProvider,
                                      ActiveBinderConfigurationProperties activeBinderConfigurationProperties) {
        super(new String[0], provisioningProvider);
        this.activeBinderConfigurationProperties = activeBinderConfigurationProperties;
    }

    public void setExtendedProperties(ActiveExtendedBindingProperties extendedProperties) {
        this.extendedProperties = extendedProperties;
    }

    @Override
    public ActiveConsumerProperties getExtendedConsumerProperties(String channelName) {
        ActiveConsumerProperties consumer = new ActiveConsumerProperties();
        BeanUtils.copyProperties(this.extendedProperties.getExtendedConsumerProperties(channelName), consumer);
        return consumer;
    }

    @Override
    public ActiveProducerProperties getExtendedProducerProperties(String channelName) {
        ActiveProducerProperties producerProperties = new ActiveProducerProperties();
        BeanUtils.copyProperties(this.extendedProperties.getExtendedProducerProperties(channelName), producerProperties);
        return producerProperties;
    }

    @Override
    protected MessageHandler createProducerMessageHandler(ProducerDestination destination,
                                                          ExtendedProducerProperties<ActiveProducerProperties> producerProperties, MessageChannel errorChannel) {

        JmsTemplate jmsTemplate = new JmsTemplate(getConnectionFactory());
        if (producerProperties.getExtension().isTransaction()) {
            jmsTemplate.setSessionTransacted(true);
        } else {
            jmsTemplate.setSessionTransacted(false);
        }

        JmsSendingMessageHandler jmsSendingMessageHandler = new JmsSendingMessageHandler(jmsTemplate);
        try {

            if (TYPE_TOPIC.equals(producerProperties.getExtension().getType())) {
                //目前不能使用
                jmsTemplate.setDefaultDestination(new MQTopic(destination.getName()));
                jmsSendingMessageHandler.setDestination(new MQTopic(destination.getName()));
            } else {
                jmsTemplate.setDefaultDestination(new MQQueue(destination.getName()));
                jmsSendingMessageHandler.setDestination(new MQQueue(destination.getName()));
            }
        } catch (JMSException e) {
           log.error("错误的创建topic",e );
        }
        jmsSendingMessageHandler.setBeanFactory(getApplicationContext());
        JmsHeaderMapper jmsHeaderMapper= new DefaultJmsHeaderMapper();
//        jmsHeaderMapper.fromHeaders(new MessageHeaders(ImmutableMap.of(
//                "x-invalid-header-name", (Object) "test",
//                "x_valid_header_name",  "test"
//        )), message);
        jmsSendingMessageHandler.setHeaderMapper(jmsHeaderMapper);

        return jmsSendingMessageHandler;
    }

    @Override
    protected MessageProducer createConsumerEndpoint(ConsumerDestination destination, String group,
                                                     ExtendedConsumerProperties<ActiveConsumerProperties> properties) {
        ActiveMessageProducerMapper producer = new ActiveMessageProducerMapper();

        JmsTemplate jmsTemplate = new JmsTemplate(getConnectionFactory());
        try {
            if (TYPE_TOPIC.equals(properties.getExtension().getType())) {
                jmsTemplate.setDefaultDestination(new MQTopic(destination.getName()));
            } else {
                jmsTemplate.setDefaultDestination(new MQQueue(destination.getName()));
            }


            jmsTemplate.setDeliveryMode(DeliveryMode.PERSISTENT);
            producer.setJmsTemplate(jmsTemplate);
            if (TYPE_TOPIC.equals(properties.getExtension().getType())) {
                producer.setDestination(new MQTopic(destination.getName()));
            } else {
                producer.setDestination(new MQQueue(destination.getName()));
            }
        } catch (JMSException e) {
           log.error("错误的创建消息：" , e);
        }
        return producer;
    }

    private CachingConnectionFactory getConnectionFactory() {
        MQQueueConnectionFactory mqQueueConnectionFactory = new MQQueueConnectionFactory();
        mqQueueConnectionFactory.setHostName(activeBinderConfigurationProperties.getHost());
        try {
            mqQueueConnectionFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
            mqQueueConnectionFactory.setCCSID(1208);
            mqQueueConnectionFactory.setChannel(activeBinderConfigurationProperties.getChannel());
            mqQueueConnectionFactory.setPort(activeBinderConfigurationProperties.getPort());
            mqQueueConnectionFactory.setQueueManager(activeBinderConfigurationProperties.getQueueManager());
        } catch (Exception e) {
            log.error("链接异常", e);
        }
        UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter = new UserCredentialsConnectionFactoryAdapter();
        userCredentialsConnectionFactoryAdapter.setUsername(activeBinderConfigurationProperties.getUserName());
        userCredentialsConnectionFactoryAdapter.setPassword(activeBinderConfigurationProperties.getPassword());
        userCredentialsConnectionFactoryAdapter.setTargetConnectionFactory(mqQueueConnectionFactory);

        CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
        cachingConnectionFactory.setTargetConnectionFactory(userCredentialsConnectionFactoryAdapter);
        cachingConnectionFactory.setSessionCacheSize(500);
        cachingConnectionFactory.setReconnectOnException(true);

        return cachingConnectionFactory;
    }
}
